学习面向对象之前 要知道 各种php或者其他编程语言的要求是 要熟悉面向对象编程 
同时这也是一种编程思想的升级

面向对象的基本概念
    ·什么对象
        世间万物皆对象
            一切可见之物都是对象
                对象的例子：桌子、车、电脑、甚至是一个人
            一切不可见之物（抽象事务）也是对象
                一些抽象的概念也可以作为一个对象

    ·对象的基本组成
        对象包含两部分
            对象的组成元素
                对象的 数据模型，用于描述对象的数据
                又被称为对象的属性，或者对象的 成员变量
            对象的行为
                对象的行为模型，用于描述对象能够做什么事情
                又被称为对象的方法

    ·对象的特点
        每个对象都是独一无二的
        对象是一个特定的事务，他的职能是完成特定的功能
        对象可以重复使用的

    ·什么是面向对象
        面向对象就是在编程的时候一直把对象放在心上
        面向对象编程就是在编程的时候数据结构（数据组织方式）都通过对象的结构进行存储
            属性 方法

    ·为什么使用面向对象
        对象的描述更加贴合真实的世界，有利于大型业务的理解
        在程序设计的过程中用对象的视角分析世界的时候能够拉近程序设计和真实世界的距离
        面向对象就是把生活中要解决的问题都用对象的方式进行存储
            属性 方法
        对象与对象之间通过方法的调用完成互动
            方法
            接球 运球 传球 -> 跑动 接球 扣篮

    面向对象的基本思路
        第一步：识别对象
            任何实体都可以被识别成为一个对象
            实例化
        第二步：识别对象的属性
            对象里面存储的数据被识别为属性
            对于不同的业务逻辑，关注的数据不同，对象里面存储的属性也不同
            设置成员属性
        第三步：识别对象的行为
            对象自己属性数据的改变
            对象和外部交互
            调用方法

    面向对象的基本原则
        对象内部是高内聚的（该有的都有 功能完善）
            对象只负责一项特定的职能（职能可大可小）
            所有对象相关内容都封装到对象内部
        对象对外是低耦合的（可以复用）
            外部世界可以看到对象的一些属性（非全部）
            外部世界可以看到对象可以做某些事情（非全部）

php中面向对象实践
    基本实践
        类的概念
            相同的属性，相同的方法，但是值不一样
            物以类聚，把具有相似特性的对象归类到一个类中
            类定义了相似对象拥有的相同的属性和方法
            类是相似对象的描述，成为类的定义，是该对象的蓝图或者原形
            类的对象成为类的一个实例
            类的属性和方法统称为类成员
            例：nba球员类
                姓名，身高，体重，所在球队，球员号码
                跑步，跳跃，运球，扣篮，传球
                nba球员实例：科比，乔丹，詹姆斯

        实例化的概念
            类的实例化就是通过类定义创建一个类的对象
                例：通过nba球员定义创建一个球员对象
            类的定义里面属性值都是空的，而对象的属性都有具体的值

            如何定义一个类
                类的定义以关键字class开始，后面跟着这个类的名称，类的命名通常每个单词的第一个字母大写，以中括号开始和结束
                class A{}
            如何实例化类的对象
                new A()
            如何调用类的方法
                ->
            构造函数
                 每一次用new实例化对象的时候，都会用类名后面的参数列表调用构造函数
                __construct
            析构函数
                在程序执行结束的时候会自动调用
                通常用于清理程序使用的资源
                __descontruct

            $this 是php里面的伪变量，表示对象自身，可以通过$this->方式访问对象的属性和方法

        类文件加载
            类文件在使用时，需要载入
                如果项目中类文件很多。就会出现载入类文件吃力：
                    两个人同时开发 代码合并的时候 引入类文件问题：
                        重复加载或者加载多余
                            以前的方法：require 所有类.class.php集中加载（保证不会重复加载但是会加载多余）

                按需加载，需要时加载，否则不加载，称之为类（文件）自动加载
                    需要：
                        判断出是否需要类，时机，完成加载
                php自动加载机制采用：当程序执行到需要类时（需要，未定义），同时该类没有被定义，此时php核心会自动调用一个默认为__autoload()的函数，并将当前需要的类名作为参数，传递到函数中
                    $obj = new Obj($params);//php核心程序调用__autoload($params);
                    function __auto($params){
                        require './'.$params.'.class.php';
                    }
                    此时，使用__autoload()就完成了类的加载，称之为类文件的自动加载
                    虽然代码写的多了 但是实现了自动化 如果需要载入多个类 则该方法会被调用多次（只需要类没有定义，就会被调用）

                自动加载业务 逻辑核心 

                    类名与类文件地址存在对应关系（自动但是需要按照规律来）
                        能够通过 类名 找到类文件的位置才可以！对应关系，php核心是处理不了的，需要人为定义，在定义类名和存储类文件时，要按照一定的规律（规则）去做。
                            比如：
                                核心类 core/
                                    DbCore.class.php
                                    libCore.class.php
                                工具类 tool/
                                    iamgeTool.class.php
                                    uploadTool.class.php
                        //根据类名加载
                        function __autoload($classname){
                            if('Core'==substr($classname,-4)){
                                require './core/'.$classname.'class.php';
                            }
                            if('Tool'==substr($classname,-4)){
                                require './tool/'.$classname.'class.php';
                            }
                            //如果存在其他的规则，再加载即可
                        }

                    实际开发中，常见规律：(效率高，类名随意但是没预见性的要提前加映射)
                        制作类名与类文件的映射列表：
                        $class_list = array(
                            'libCore' => './core/libCore.class.php',
                            'DbCore' => './core/ibCore.class.php',
                        );
                        先判断类是否存在于映射列表中
                        function __autoload($classname){
                            if(isset($class_list[$classname]){
                                require $class_list[$classname];
                            }
                        }

                        function __autoload($classname){
                            if(isset($class_list[$classname]){
                                require $class_list[$classname];
                            }
                            elseif('Core'==substr($classname,-4)){
                                require './core/'.$classname.'class.php';
                            }
                            elseif('Tool'==substr($classname,-4)){
                                require './tool/'.$classname.'class.php';
                            }
                            //如果存在其他的规则，再加载即可
                        }

                默认__autoload()为自动加载，有局限：
                其一：不能存在多个
                    项目多个模块开发，存在不同模块的自动加载
                    项目如果使用第三方模块，也会由第三方定义自动加载(Smarty)
                其二：如果注册了新的自动加载则默认的自动加载失效

                    可见，需要特殊的名字，作为自动加载函数名
                    告知php核心，自动加载函数名
                        spl_autoload_register('自定义自动加载函数名');
                        在使用类之前：注册一个自动加载函数
                    通常会在定义函数前就注册好
                    一旦注册了额外的自动加载函数，则默认的__autoload()就不起作用了
                    php允许注册多个额外的自动加载。并且在需要类时，会依据注册的顺序，逐一调用自动加载类

        Db.class.php

    高级实践
        继承

            运动员：姓名 身高 体重 所在球队 球员号码 讲话 行走 扣篮 运球  
            演员：姓名 身高 体重 艺名 所属公司 讲话 行走 唱歌 演戏
            可以把公用的成员提取出来
            他们拥有部分相同的属性和方法 因为他们都是人类

            继承的好处
                父类里面定义的成员可以不用再子类中重复定义，节约了变成的时间和代价
                同一父类的子类拥有相同的父类定义类的成员，因此外部调用他们的时候可以一视同仁
                子类可以修改和调整父类定义的类成员  
                    我们称之为重写，一旦类修改了，就按照子类修改之后的功能执行

            在php中可以用extends关键字来标示类的继承，后面跟父类的类名
            extends后面只能跟一个类的类名，这就是php中的单继承原则

        访问控制
            public 公有类成员 可以在任何地方被访问
            protected 受保护的类成员，可以被其自身以及子类访问
            private 私有的类成员，只能被自身访问

        static（静态）关键字
            使类的静态成员特性就可以共用属性
            静态属性定义时在访问控制关键字后面添加static关键字即可
            在类定义中使用静态成员的时候，用self或者static关键字紧跟着::操作符调用
            在定义外部访问静态属性，我们可以用类名加::操作符的方法来访问类的静态成员
            使用parent关键字技能访问父类的静态成员
            静态方法里面只能访问静态属性
            访问 类名::方法名()或者$属性名
            例：改变共有属性 public static $cate = 'people';

        重写
            子类中编写跟父类完全一致的方法可以完成对父类方法的重写

        final关键字
            不希望子类修改
            不希望再创建他的子类
            添加final关键字能够让这个方法不能再子类中重写
            对于不想被任何类继承的类可以在class之前添加final关键字

        数据访问补充
            用parent关键字可以访问父类中被子类重写的方法
            const 定义常量
            self::常量名
            self关键字可以用于访问类自身的成员方法，也可以用于访问自身的静态成员和类常量；不能用于访问类自身的属性；使用常量的时候不需要在常量名称前面加$符号

        接口
            问题
                人会吃饭，动物也会吃饭
            吃这个动作（方法）动物和植物的实现方式是不一样的
                吃这个行为没有统一的实现方式
                动物张嘴咀嚼
                之物直接包裹融化
            接口就是把不同类的共同行为进行了定义，然后在不同类里面实现不同的功能

            一旦某个类实现了某个接口，那么久必须实现接口定义的方法
                人这个类实现了“会吃东西”这个接口，那么人必须实现接口定义的“吃饭”方法

                interface icaneat{
                    public function eat($food);
                }
                class humen implements icantet{
                    public function eat($food){

                    }
                }

                interface关键字用于定义接口
                接口里面的方法不需要有方法实现
                实现了某个接口之后，必须提供接口中定义的方法具体实现
                不能实例化接口
                判断对象是否实现了某个接口 对象 instanceof 接口

                function checkeat($obj){
                    if($obj instanceof icaneat){
                        $obj->eat('food');
                    }else{
                        echo '没有实现接口';
                    }
                }

                可以用extends让接口继承接口
                当类实现子接口时，父接口定义的方法也需要在这个类里面具体实现

        多态
            因为接口的方法实现可以有很多，所以对于接口里面定义的方法具体实现是多种多样的，这种特性我们称为多态
                比如接口A有两个实现B和C，B和C对A里面定义的方法的实现可以是不同的，这种现象就是多态

        抽象类
            接口里面的方法都是没有实现的，而类里面的方法都是有实现的
                当接口中的某些方法对于所有的实现类都是一样的实现方法，只有部分方法需要用到多态的特性
                例如：人和动物吃东西是不同的，但是呼吸时相同的，不需要为人和动物分别实现呼吸的功能
            abstract class acaneat{
                abstract public function eat($food);

                public function breath(){

                }
            }

            class humen extends acaneat{
                public function eat(){

                }
            }
            抽象类中可以包含普通的方法，有方法的具体实现
            继承抽象类的子类需要实现抽象类中定义的抽象方法

        Db.class.php

    设计模式
        单例|单例模式
            单个实例，实例就是对象
            单例：单个对象
            语法上一个类可以实例化无数个对象
            设计思想：
                如果一个类的一个对象就可以完成所有的功能
                    例如：通常的项目中，只需要操作一个数据库服务器，完成所有的功能。因此仅仅需要一个数据库操作对象即可。

                既然存在一个对象可以完成功能的对象，就需要在语法层面上，限制该类去得到多个对象，只能得到一个对象，目的为了节约对象成本，这种设计，就被成为单例设计

            私有化构造方法
                限制在类外实例化对象，结果不能实例化对象，如何实例化对象？
                如果可以在类内调用该构造方法，就可以完成实例化工作了
            静态的公共方法
                在没有对象前，可以使用类调用静态方法的方式
            静态的私有方法
                完善公共静态方法的业务逻辑，保证即使多次调用也只能得到一个对象
                核心在于，第一次可以将对象存储起来，第二次调取对象
            私有化克隆方法
                禁止被克隆

            class A{
                //三私一公
                private static $class;
                private function __construct(){
                }
                private function __clone(){
                }
                public static function newClass(){
                    if(!isset(static::$class)){
                        static::$class = new A();
                    }
                    return static::$class;
                }
            }

            单例的另一种表现形式
                function getOne(){
                    static $class = null;
                    if(!isset($class)){
                        $class = new A();
                    }
                    return $class;
                }
                劣势：并没有从根本上解决单例问题，仍然可以new出来
                优势：灵活，不需要去更改类本身的结构，可以做到同时适应多个类

                如果想实现其他类的单例，可以传参数
                function getOne($classname){
                    static $classlist = array();
                    if(!isset($classlist[$classname])){
                        $classlist[$classname] = new $classname();
                    }
                    return $classlist[$classname];
                }

            所以实际开发中：
                如果要严格限制单例效果，使用三私一公单例模式，如果仅仅想实现单例效果，就使用类外的实现

        工厂模式
            从类的功能上讲，如果某个类的主要功能，用来生产其他类的对象，这样的类，称之为工厂类


    特殊实践（只有php中有的）
        魔术方法
            __tostring()当对象当做string使用时，这个方法会被自动调用
            echo $obj

            __invoke($params)
            当对象被当成方法调用时，这个方法会被自动调用
            $obj();

            __call($name,$params)
            当对象访问不存在的方法名称时，__call方法会被自动调用
            这个方法的参数第一个就是调用的方法名称，第二个参数是方法调用的参数组成的数组

            __callStatic()
            当对象访问不存在的静态方法名称时，__callStatic方法会被自动调用
            这两个方法在php里面也被成为方法的重载

            __get($name)
                读取不可访问属性的值时，会被调用
            __set($name,$value)
                在给不可访问属性赋值时，会被调用
            __isset($name)
                当对不可访问属性调用isset()或empty()时，__isset()会被调用
            __unset($name)
                当对不可访问属性调用时，会被调用

            所谓不可访问属性，实际上就是在调用某个属性时发现这个属性没有被定义，这时候不同的操作会触发不同的魔术方法
            这几个方法也被称为属性重载的魔术方法

            __clone()
                $obj1 = $obj2 址传递   clone实现复制





工厂模式
class Factory{
    //生产线
    public static function getClass($class){
        static $classList = array();
        if(!isset($classList[$class])){
           $classList[$class] = new $class();
        }
        return $classList[$class];
    }
}


魔术常量
__FILE__
__LINE__
__DIR__
__FUNCTION__
__CLASS__
__METHOD__

相关函数
class_exists(类名)

method_existes(对象，方法名)

property_exists(对象，属性名)

interface_exists(接口名)

get_class(对象)

get_called_class()得到调用该方法的类

get_parent_class(类名)得到类的父类

is_object()判断是否是对象

is_a(对象，类名) instanceof判断是否是某个类的实例